using System;
using System.Collections.Generic;
using System.Text;

namespace ImagesMath
{
public class PR3
  {
    

    private double x, y, z;                             

    #region Constructors

    public PR3(double x, double y, double z)
    {

          this.x = x;
          this.y = y;
          this.z = z;
     }
    public PR3(VR3 v)
    {
      this.x = v.X;
      this.y = v.Y;
      this.z = v.Z;
    }

    #endregion

    #region Accessors

    public double X
    {
      get { return this.x; }
      set { this.x = value; }
    }
    public double Y
    {
      get { return this.y; }
      set { this.y = value; }
    }
    public double Z
    {
      get { return this.z; }
      set { this.z = value; }
    }

    #endregion

    #region arithmetical operators

    public static PR3 operator+(PR3 p1, VR3 v1)
    {
        return new PR3(p1.X + v1.X, p1.Y + v1.Y, p1.Z + v1.Z);
    }

    public static PR3 operator -(PR3 p1)
    {
        return new PR3(-p1.X, -p1.Y, -p1.Z);
    }


    public static VR3 operator -(PR3 p1, PR3 p2)
    {
        return new VR3(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z);
    }

    public static PR3 operator *(PR3 p1, double k)
    {
        return new PR3(p1.X * k, p1.Y * k, p1.Z * k);
    }

    public static PR3 operator /(PR3 p1, double k)
    {
        if (k > ImageMath.EPS)
        {
            return new PR3(p1.X / k, p1.Y / k, p1.Z / k);
        }
        else
        {
            return p1;
        }
    }
    public static PR3 operator /(PR3 p, VR3 v)
    {

        if (v.X > ImageMath.EPS && v.Y > ImageMath.EPS && v.Z > ImageMath.EPS)
        {
            return new PR3(p.X / v.X, p.Y / v.Y, p.Z / v.Z);
        }
        else
        {
            return p;
        }
        
    }

    public static bool operator ==(PR3 p1, PR3 p2)
    {
        return (p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z);

    }
    public static bool operator !=(PR3 p1, PR3 p2)
    {
        return (!(p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z));
    }


    #endregion

    #region Functions
    //// friendly functions
    public void toPolar(ref PR3 p,ref double theta,ref double phi,ref double rho) 
    {

        double rophi, costheta, sinphi;

        rophi = Math.Sqrt((p.X * p.X) + (p.Z * p.Z));
        rho = Math.Sqrt((p.X * p.X) + (p.Y * p.Y) + (p.Z * p.Z));

        if (rophi == 1)
        {
            costheta = (p.X / rophi);
        }
        else
        {
            costheta = 1.0;
        }
        if (rho == 1)
        {
            sinphi = (p.y / rho);
        }
        else
        {
            sinphi = 0.0;
        }
        phi = Math.Asin(sinphi);
        theta = Math.Acos(costheta);
        if (p.Z < 0.0) theta = -theta;
    }
    public void fromPolar(double theta, double phi, double rho, ref PR3 p) 
    {

        p.X = Math.Cos(phi) * Math.Cos(theta) * rho;
        p.Z = Math.Cos(phi) * Math.Sin(theta) * rho;
        p.Y = Math.Sin(phi) * rho;
    }

    //      friend std::ostream & operator << (std::ostream &o,const pR3 &p);

    #endregion

};
}


